/*!
 * \file was_ejb.c
 *
 * \brief was ejb 数据包解析
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 *
 * \version 3.0
 * \author wuwk
 * \date 2016/03/21
 *
 */

#include <stdio.h>
#include <iconv2utf8.h>

#include "corba_comm.h"
#include "ejb_comm.h"

union int32_float_bits {
    int32_t int_bits;
    float float_bits;
};

union int64_double_bits {
    int64_t int_bits;
    double double_bits;
};


/*!
 * 对齐
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param i_pos                (int 首位置)
 * \param i_alignment          (int 对齐位数)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int __alignment(Frbyte_Packet *p_st_data, int i_pos, int i_alignment)
{
    if (p_st_data == NULL)
        return FR_FAIL;

    while(((bytebuff_getPosition(p_st_data) - i_pos) % i_alignment) != 0)
    {
        if (bytebuff_skip(p_st_data, 1) == FR_FAIL)
            return FR_FAIL;
    }

    return FR_SUCC;
}

/*!
 * boolean数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t 数组个数)
 * \param *p_key               (char    上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_boolean_array(Frbyte_Packet *p_st_data
                                  , Frreport_body_data *p_st_body_data
                                  , uint32_t u32_count
                                  , char *p_key)
{
    char *p_buff = NULL;
    uint8_t u8_boolean = 0;
    int i_buff_size = 0;
    int i_left_size = 0;
    int i = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    i_buff_size = u32_count * 7 + 1;
    p_buff = (char *)frmalloc(i_buff_size);
    if (p_buff == NULL)
        return FR_FAIL;

    snprintf(p_buff, i_buff_size, "[");
    i_left_size = i_buff_size - 1;

    for (; i < (int)u32_count; i++)
    {
        if (bytebuff_get_char(p_st_data, &u8_boolean) == FR_FAIL)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        if (u8_boolean == 0)
        {
            snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "false,");
            i_left_size -= 6;
        }
        else if (u8_boolean == 1)
        {
            snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "true,");
            i_left_size -= 5;
        }
        else
        {
            frfree(p_buff);
            return FR_FAIL;
        }
    }
    p_buff[i_buff_size - i_left_size - 1] = ']';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_buff) == FR_FAIL)
    {
        frfree(p_buff);
        return FR_FAIL;
    }

    frfree(p_buff);

    return FR_SUCC;
}

/*!
 * byte数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t 数组个数)
 * \param *p_key               (char    上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_byte_array(Frbyte_Packet *p_st_data
                               , Frreport_body_data *p_st_body_data
                               , uint32_t u32_count
                               , char *p_key)
{
    char *p_buff = NULL;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    p_buff = (char *)frmalloc(u32_count + 1);
    if (p_buff == NULL)
        return FR_FAIL;

    if (bytebuff_get_bytes(p_st_data, p_buff, u32_count) == FR_FAIL)
    {
        frfree(p_buff);
        return FR_FAIL;
    }

    // 上报
    if (frreport_body_l7_add_bin(p_st_body_data, p_key, p_buff, u32_count) == FR_FAIL)
    {
        frfree(p_buff);
        return FR_FAIL;
    }

    frfree(p_buff);

    return FR_SUCC;
}

/*!
 * char数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t  数组个数)
 * \param *p_key               (char    上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_char_array(Frbyte_Packet *p_st_data
                               , Frreport_body_data *p_st_body_data
                               , uint32_t u32_count
                               , char *p_key)
{
    char *p_buff = NULL;
    char *p_utf8 = NULL;
    char arr_char[16];
    int i_buff_size = 0;
    int i_left_size = 0;
    unsigned int ui_utf8_len = 0;
    uint8_t u8_len = 0;
    int i = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    i_buff_size = bytebuff_remaining(p_st_data) * 3 + 1;
    p_buff = (char *)frmalloc(i_buff_size);
    if (p_buff == NULL)
        return FR_FAIL;

    snprintf(p_buff, i_buff_size, "[");
    i_left_size = i_buff_size - 1;

    for (; i < (int)u32_count; i++)
    {
        if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
            goto err;

        if (bytebuff_get_bytes(p_st_data, arr_char, u8_len) == FR_FAIL)
            goto err;

        arr_char[u8_len] = '\0';

        if (u8_len > 1)
        {
            i_ret = iconv_to_utf8(arr_char, u8_len, (char *)"UNICODEBIG", &p_utf8, &ui_utf8_len);
            if (i_ret == 1)
            {
                frfree(p_utf8);
                goto err;
            }
            else if (i_ret == 2)
                goto err;

            snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "'%s',", p_utf8);
            i_left_size -= 4;

            frfree(p_utf8);
        }
        else
        {
            snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "'%s',", arr_char);
            i_left_size -= 4;
        }
    }

    p_buff[i_buff_size - i_left_size - 1] = ']';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_buff) == FR_FAIL)
        goto err;

    frfree(p_buff);

    return FR_SUCC;

err:
    if (p_buff)
        frfree(p_buff);

    return FR_FAIL;
}

/*!
 * short数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t 数组个数)
 * \param *p_key               (char    上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_short_array(Frbyte_Packet *p_st_data
                               , Frreport_body_data *p_st_body_data
                               , uint32_t u32_count
                               , char *p_key)
{
    char *p_buff = NULL;
    char arr_short[11];
    int i_buff_size = 0;
    int i_left_size = 0;
    int i = 0;
    uint16_t u16_short = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    i_buff_size = bytebuff_remaining(p_st_data) * 3 + 1;
    p_buff = (char *)frmalloc(i_buff_size);
    if (p_buff == NULL)
        return FR_FAIL;

    snprintf(p_buff, i_buff_size, "[");
    i_left_size = i_buff_size - 1;

    for (; i < (int)u32_count; i++)
    {
        if (bytebuff_remaining(p_st_data) < 2)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        if (bytebuff_get_short(p_st_data, 2, &u16_short, BYTE_BIG_ENDIAN) == FR_FAIL)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        snprintf(arr_short, sizeof(arr_short), "%d", u16_short);
        snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "%s,", arr_short);
        i_left_size -= (strlen(arr_short) + 1);
    }
    p_buff[i_buff_size - i_left_size - 1] = ']';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_buff) == FR_FAIL)
    {
        frfree(p_buff);
        return FR_FAIL;
    }

    frfree(p_buff);

    return FR_SUCC;
}

/*!
 * int数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t 数组个数)
 * \param *p_key               (char    上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_int_array(Frbyte_Packet *p_st_data
                              , Frreport_body_data *p_st_body_data
                              , uint32_t u32_count
                              , char *p_key)
{
    char *p_buff = NULL;
    char arr_int[11];
    int i_buff_size = 0;
    int i_left_size = 0;
    int i = 0;
    uint32_t u32_int = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    i_buff_size = bytebuff_remaining(p_st_data) * 3 + 1;
    p_buff = (char *)frmalloc(i_buff_size);
    if (p_buff == NULL)
        return FR_FAIL;

    snprintf(p_buff, i_buff_size, "[");
    i_left_size = i_buff_size - 1;

    for (; i < (int)u32_count; i++)
    {
        if (bytebuff_remaining(p_st_data) < 4)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        if (bytebuff_get_int(p_st_data, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        snprintf(arr_int, sizeof(arr_int), "%d", u32_int);
        snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "%s,", arr_int);
        i_left_size -= (strlen(arr_int) + 1);
    }
    p_buff[i_buff_size - i_left_size - 1] = ']';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_buff) == FR_FAIL)
    {
        frfree(p_buff);
        return FR_FAIL;
    }

    frfree(p_buff);

    return FR_SUCC;
}

/*!
 * long数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t 数组个数)
 * \param *p_key               (char    上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_long_array(Frbyte_Packet *p_st_data
                               , Frreport_body_data *p_st_body_data
                               , uint32_t u32_count
                               , char *p_key)
{
    char *p_buff = NULL;
    char arr_long[11];
    int i_buff_size = 0;
    int i_left_size = 0;
    int i = 0;
    uint64_t u64_long = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    i_buff_size = bytebuff_remaining(p_st_data) * 3 + 1;
    p_buff = (char *)frmalloc(i_buff_size);
    if (p_buff == NULL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 4);

    snprintf(p_buff, i_buff_size, "[");
    i_left_size = i_buff_size - 1;

    for (; i < (int)u32_count; i++)
    {
        if (bytebuff_remaining(p_st_data) < 8)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        if (bytebuff_get_long(p_st_data, 8, &u64_long, BYTE_BIG_ENDIAN) == FR_FAIL)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        snprintf(arr_long, sizeof(arr_long), "%ld", u64_long);
        snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "%s,", arr_long);
        i_left_size -= (strlen(arr_long) + 1);
    }
    p_buff[i_buff_size - i_left_size - 1] = ']';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_buff) == FR_FAIL)
    {
        frfree(p_buff);
        return FR_FAIL;
    }

    frfree(p_buff);

    return FR_SUCC;
}

/*!
 * float数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t 数组个数)
 * \param *p_key               (char    上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_float_array(Frbyte_Packet *p_st_data
                                , Frreport_body_data *p_st_body_data
                                , uint32_t u32_count
                                , char *p_key)
{
    char *p_buff = NULL;
    char arr_float[64];
    int i_buff_size = 0;
    int i_left_size = 0;
    int i = 0;
    uint32_t u32_int = 0;
    union int32_float_bits u_32bits;
    float f_value = 0.0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    i_buff_size = bytebuff_remaining(p_st_data) * 12 + 1;
    p_buff = (char *)frmalloc(i_buff_size);
    if (p_buff == NULL)
        return FR_FAIL;

    snprintf(p_buff, i_buff_size, "[");
    i_left_size = i_buff_size - 1;

    for (; i < (int)u32_count; i++)
    {
        if (bytebuff_remaining(p_st_data) < 4)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        if (bytebuff_get_int(p_st_data, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        u_32bits.int_bits = u32_int;
        f_value = u_32bits.float_bits;

        snprintf(arr_float, sizeof(arr_float), "%f", f_value);
        snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "%s,", arr_float);
        i_left_size -= (strlen(arr_float) + 1);
    }
    p_buff[i_buff_size - i_left_size - 1] = ']';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_buff) == FR_FAIL)
    {
        frfree(p_buff);
        return FR_FAIL;
    }

    frfree(p_buff);

    return FR_SUCC;
}

/*!
 * double数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t 数组个数)
 * \param *p_key               (char    上报key)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_double_array(Frbyte_Packet *p_st_data
                                 , Frreport_body_data *p_st_body_data
                                 , uint32_t u32_count
                                 , char *p_key)
{
    char *p_buff = NULL;
    char arr_long[512];
    int i_buff_size = 0;
    int i_left_size = 0;
    int i = 0;
    uint64_t u64_long = 0;
    union int64_double_bits u_64bits;
    double db_value = 0.0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    i_buff_size = bytebuff_remaining(p_st_data) * 47 + 1;
    p_buff = (char *)frmalloc(i_buff_size);
    if (p_buff == NULL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 4);

    snprintf(p_buff, i_buff_size, "[");
    i_left_size = i_buff_size - 1;

    for (; i < (int)u32_count; i++)
    {
        if (bytebuff_remaining(p_st_data) < 8)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        if (bytebuff_get_long(p_st_data, 8, &u64_long, BYTE_BIG_ENDIAN) == FR_FAIL)
        {
            frfree(p_buff);
            return FR_FAIL;
        }

        u_64bits.int_bits = u64_long;
        db_value = u_64bits.double_bits;

        snprintf(arr_long, sizeof(arr_long), "%lf", db_value);
        snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "%s,", arr_long);
        i_left_size -= (strlen(arr_long) + 1);
    }
    p_buff[i_buff_size - i_left_size - 1] = ']';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_buff) == FR_FAIL)
    {
        frfree(p_buff);
        return FR_FAIL;
    }

    frfree(p_buff);

    return FR_SUCC;
}

/*!
 * string数组解析并上报
 *
 * \param *p_st_data           (Frbyte_Packet         数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param u32_count            (uint32_t 数组个数)
 * \param *p_key               (char    上报key)
 * \param i_pos             (int 数据开始位置)
 * \param i_type            (int weblogic/was)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *
 */
int ejb_rtn_string_array(Frbyte_Packet *p_st_data
                                 , Frreport_body_data *p_st_body_data
                                 , uint32_t u32_count
                                 , char *p_key
                                 , int i_pos
                                 , int i_type)
{
    char *p_buff = NULL;
    char *p_data = NULL;
    char *p_utf8 = NULL;
    unsigned int ui_utf8_len = 0;
    uint32_t u32_chunk = 0;
    uint32_t u32_len = 0;
    int i_buff_size = 0;
    int i_left_size = 0;
    int i = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    if (bytebuff_peek_int(p_st_data, 4, &u32_chunk, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    // 7f ff ff 02
    if (u32_chunk != 2147483394 && u32_chunk != 2147483402)
        return FR_SUCC;

    bytebuff_skip(p_st_data, 4);

    // String描述符长度
    if (bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;
    bytebuff_skip(p_st_data, u32_len);

    // 对齐
    if (__alignment(p_st_data, i_pos, 4) == FR_FAIL)
        return FR_FAIL;

    i_buff_size = bytebuff_remaining(p_st_data) + 1;
    p_buff = (char *)frmalloc(i_buff_size);
    if (p_buff == NULL)
        return FR_FAIL;

    snprintf(p_buff, i_buff_size, "[");
    i_left_size = i_buff_size - 1;

    for (; i < (int)u32_count; i++)
    {
        if (i != 0)
        {
            if (bytebuff_peek_int(p_st_data, 4, &u32_chunk, BYTE_BIG_ENDIAN) == FR_FAIL)
                goto err;

            if (u32_chunk == 4294967295) // ff ff ff ff
            {
                if (bytebuff_skip(p_st_data, 8) == FR_FAIL)
                    goto err;
                snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "\"\",");
                i_left_size -= 3;
                continue;
            }
            else if (u32_chunk != 2147483394 && u32_chunk != 2147483402)
                goto err;
            else
            {
                if (bytebuff_skip(p_st_data, 12) == FR_FAIL)
                    goto err;
            }
        }

        if (bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
            goto err;

        if (u32_len == 0)
        {
            snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "\"\",");
            i_left_size -= 3;
            continue;
        }

        p_data = (char *)frmalloc(u32_len + 1);
        if (p_data == NULL)
            return FR_FAIL;

        if (bytebuff_get_bytes(p_st_data, p_data, u32_len) == FR_FAIL)
            goto err;
        p_data[u32_len] = '\0';

        if (i_type == IS_WAS)
        {
            i_ret = iconv_to_utf8(p_data, u32_len, (char *)"UNICODEBIG", &p_utf8, &ui_utf8_len);
            if (i_ret == 1)
            {
                frfree(p_utf8);
                goto err;
            }
            else if (i_ret == 2)
                goto err;

            snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "\"%s\",", p_utf8);
            i_left_size -= (ui_utf8_len + 3);

            frfree(p_data);
            frfree(p_utf8);
        }
        else if (i_type == IS_WEBLOGIC)
        {
            snprintf(p_buff + (i_buff_size - i_left_size), i_left_size, "\"%s\",", p_data);
            i_left_size -= (u32_len + 3);

            frfree(p_data);
        }
        else
            goto err;

        p_data = NULL;

        if (i != (int)(u32_count - 1))
        {
            // 对齐
            if (__alignment(p_st_data, i_pos, 4) == FR_FAIL)
                return FR_FAIL;
        }
    }
    p_buff[i_buff_size - i_left_size - 1] = ']';

    // 上报
    if (frreport_body_l7_add_str(p_st_body_data, p_key, p_buff) == FR_FAIL)
        goto err;

    frfree(p_buff);

    return FR_SUCC;

err:
    if (p_buff)
        frfree(p_buff);

    if (p_data)
        frfree(p_data);

    return FR_FAIL;
}
